﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using WebSocketSharp;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using YB;
using System.Collections.Generic;
using System.Collections.Concurrent;
using Fleck;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using YB_Server_Windows;
using static NPOI.HSSF.Util.HSSFColor;

namespace YB_PrintPlug
{
    public partial class PrintPlug : UserControl
    {
        private class PrintChannel
        {
            public string _PrintName = "";
            public string _LastTaskId = "";
            private ConcurrentQueue<string> _sendData = new ConcurrentQueue<string>();
            private bool _waitNext = false;
            private static ManualResetEvent waitPlugReturn = new ManualResetEvent(false);//当前通道阻塞
            public List<string> errlist = new List<string>();
            private PrintPlug _plug { get; set; }
            public PrintChannel(string printname, string data, PrintPlug plug)
            {
                this._sendData.Enqueue(data);
                this._PrintName = printname;
                this._plug = plug;
                Init();
            }
            public void Send(string data)
            {
                _sendData.Enqueue(data);
            }
            public void Clear()
            {
                while (_sendData.TryDequeue(out var _)) { }
                if (_waitNext)
                {
                    _waitNext = false;
                    waitPlugReturn.Set();
                }
            }
            public void Continue()
            {
                if (_waitNext)
                {
                    _waitNext = false;
                    waitPlugReturn.Set();
                }
            }
            void _init()
            {
                while (_sendData.Count > 0)
                {
                    Thread.Sleep(200);//每个打印任务之间间隔50毫秒
                    string data;
                    if (_sendData.TryDequeue(out data))
                    {
                        JObject sendData = JObject.Parse(data);
                        if (sendData != null)
                        {
                            string nowTaskId = "";
                            YB.Config.ReadJObject(sendData, "requestID", ref nowTaskId);
                            if (nowTaskId == "")
                            {
                                YB.Config.ReadJObject<string>(sendData, "key", ref nowTaskId);
                            }
                            if (nowTaskId != "")
                            {
                                _plug._SendCount++;
                                _plug.SendMsg(data);
                                _LastTaskId = nowTaskId;
                                //YB.Log.Write("$打印组件:[" + _plug.Label + "]中，给打印机" + _PrintName + "发送消息" + data);
                                _waitNext = true;
                                waitPlugReturn.Reset();
                                //YB.Log.Write("$打印组件:[" + _plug.Label + "]中，当前等待的ID[" + _LastTaskId + "],等待打印结束");
                                waitPlugReturn.WaitOne();
                                //YB.Log.Write("$打印组件:[" + _plug.Label + "]中，继续打印");
                            }
                            else
                            {
                                YB.Log.Write("发送给打印组件错误，无法识别任务ID[" + _plug.Label + "][" + _PrintName + "][" + data + "]");
                            }
                        }
                    }
                }
                YB.Log.Write("$打印组件:[" + _plug.Label + "]中，通道通道[" + _PrintName + "]已完成，结束打印任务");
                _plug.Remove(_PrintName);
            }
            void Init()
            {
                Thread thisthread = new Thread(_init);
                thisthread.Start();
            }
        }
        private Color _backColor;
        private Image _imageData = null;
        private bool _linkStatus = false;
        private long _receiveCount = 0;
        private bool _inLink = false;
        private object _lockObject = new object();

        public bool LinkStatus
        {
            get { return _linkStatus; }
        }
        private string _label = "";
        public string Label
        {
            get { return _label; }
            set
            {
                _label = value;
                Invalidate();
            }
        }
        private string _kind = "";
        private string _ip = "";
        private string _prot = "";
        private long _SendCount = 0;
        private string _downloadLink = "";
        private bool mouseinplug = false;
        private Action<string> _onPause { get; set; }
        private Action<string, IWebSocketConnection> _onMessage = null;
        public Action<string, IWebSocketConnection> OnMessage
        {
            get { return _onMessage; }
            set { _onMessage = value; }
        }
        private WebSocketSharp.WebSocket _sendSocket = null;
        private IWebSocketConnection _socket = null;
        private ConcurrentDictionary<string, PrintChannel> _printMap = new ConcurrentDictionary<string, PrintChannel>();
        bool Remove(string printname)
        {
            return _printMap.TryRemove(printname, out _);
        }
        public PrintPlug(string label, string kind, string ip, string prot, Image imagedata, string downloadLink)
        {
            _label = label;
            _kind = kind;
            _ip = ip;
            _prot = prot;
            _imageData = imagedata;
            _downloadLink = downloadLink;
            InitializeComponent();
            _backColor = this.BackColor;
            this.BackColor = Color.Transparent;
            this.DoubleBuffered = true;
            Invalidate();
            //开始端口检测
            if (_ip != "" && _prot != "")
            {
                Init();
            }
        }

        void onmessage(Object sender, MessageEventArgs e)
        {
            _receiveCount++;
            Invalidate();
            string taskId = CheckPrintOver(e.Data);
            //YB.Log.Write("收到组件消息["+_kind+"]["+ _label + "]" + e.Data);
            if (_onMessage != null)
            {
                _onMessage?.Invoke(e.Data, _socket);
            }
            if (taskId != "")
            {
                bool Checked = false;
                foreach (string key in _printMap.Keys)
                {
                    if (_printMap.TryGetValue(key, out PrintChannel value))
                    {
                        Log.Write("比对任务号" + value._LastTaskId + "[" + value._LastTaskId.Length + "]" + taskId + "[" + taskId.Length + "]");
                        if (value._LastTaskId.Trim() == taskId.Trim())
                        {
                            value.Continue();
                            Thread.Sleep(100);
                            //YB.Log.Write("任务" + taskId + "打印完成，打印机[" + value._PrintName + "]，继续打印");
                            Printlist.RecoverPrint(value._PrintName, taskId);
                            main.UpdatePrintListTask(value._PrintName, taskId, "打印完成");
                            Checked = true;
                            break;
                        }
                    }
                }
                if (!Checked)
                {
                    YB.Log.Write("打印结束错误[" + taskId + "]任务没有找到");
                }
            }
        }
        void onClick(object sender, EventArgs e)
        {
            if (mouseinplug && !_linkStatus)
            {
                //转到下载
                YB.Base.OpenUrl(_downloadLink);
            }
        }
        void onMouseLeave(object sender, EventArgs e)
        {
            if (mouseinplug)
            {
                mouseinplug = false;
                Invalidate();
            }
        }
        void onMouseEnter(object sender, EventArgs e)
        {
            if (!_linkStatus)
            {
                mouseinplug = true;
                Invalidate();
            }
        }
        void onopen(Object sender, EventArgs e)
        {
            _linkStatus = true;
            Invalidate();
        }
        void onclose(Object sender, CloseEventArgs e)
        {
            _linkStatus = false;
            Invalidate();
            if (e.Code == 1001)
            {
                Thread.Sleep(1000); // 等待一段时间再重新连接
                _sendSocket.Connect();
            }
            else
            {
                Log.Write("打印组件" + _label + "断开链接,错误类型[" + e.Reason + "]错误代码[" + e.Code.ToString() + "]");
                if (_sendSocket != null)
                {
                    _sendSocket.Close();
                }
                _sendSocket = null;
                Init();
            }
        }
        private void Init()
        {
            if (!_inLink)
            {
                _inLink = false;
                Thread thisthread = new Thread(_init);
                thisthread.Start();
            }
        }
        private string CheckPrintOver(string data)
        {
            JObject json = JObject.Parse(data);
            if (json == null)
            {
                return "";
            }
            string cmd = "";
            string status = "";
            string taskId = "";

            switch (_kind)
            {
                case "548":
                    Config.ReadJObject<string>(json, "cmd", ref cmd);
                    Config.ReadJObject<string>(json, "taskStatus", ref status);
                    Config.ReadJObject<string>(json, "taskID", ref taskId);

                    Log.Write("收到组件[" + _label + "]菜鸟消息" + data);
                   
                    if (cmd.ToLower() == "notifyprintresult" && status.ToLower() == "rendered")
                    {
                        Log.Write("菜鸟打印完成["+ taskId + "]");
                        goto Next;
                    }
                    //if (cmd.ToLower() == "notifyprintresult")
                    //{
                    //    string taskStatus = "";
                    //    Config.ReadJObject<string>(json, "taskStatus", ref taskStatus);
                    //    Config.ReadJObject<string>(json, "taskID", ref taskId);
                    //    if (taskStatus.ToLower() == "printed" && taskId != "")
                    //    {
                    //        goto Next;
                    //    }
                    //}
                    break;
                case "615":
                    Config.ReadJObject<string>(json, "cmd", ref cmd);
                    Config.ReadJObject<string>(json, "taskStatus", ref status);
                    Config.ReadJObject<string>(json, "taskID", ref taskId);
                    if (cmd.ToLower() == "notifyprintresult" && status.ToLower() == "printed")
                    {
                        //YB.Log.Write("615打印完成下一个");
                        //if (taskId != "")
                        //{
                        //    AddPrintLog(printName, "文档[" + taskId + "]打印完成");
                        //}
                        goto Next;
                    }
                    break;
                case "566":
                    Config.ReadJObject<string>(json, "cmd", ref cmd);
                    Config.ReadJObject<string>(json, "taskStatus", ref status);
                    Config.ReadJObject<string>(json, "taskID", ref taskId);
                    if (cmd.ToLower() == "printresultnotify" && status.ToLower() == "printed")
                    {
                        //YB.Log.Write("566打印完成下一个");
                        //if (taskId != "")
                        //{
                        //    AddPrintLog(printName, "文档[" + taskId + "]打印完成");
                        //}
                        goto Next;
                    }
                    break;
                case "544":
                    Config.ReadJObject<string>(json, "message", ref cmd);
                    Config.ReadJObject<string>(json, "key", ref taskId);
                    if (cmd.ToLower().IndexOf("print") > -1 && cmd.ToLower().IndexOf("success") > -1)
                    {
                        //YB.Log.Write("544打印完成下一个");
                        //if (taskId != "")
                        //{
                        //    AddPrintLog(printName, "文档[" + taskId + "]打印完成");
                        //}
                        goto Next;
                    }
                    break;
                case "633":
                    Config.ReadJObject<string>(json, "cmd", ref cmd);
                    Config.ReadJObject<string>(json, "taskStatus", ref status);
                    Config.ReadJObject<string>(json, "taskID", ref taskId);
                    if (cmd.ToLower() == "notifyprintresult" && status.ToLower() == "printed")
                    {
                        //YB.Log.Write("633打印完成下一个");
                        //if (taskId != "")
                        //{
                        //    AddPrintLog(printName, "文档[" + taskId + "]打印完成");
                        //}
                        goto Next;
                    }
                    break;
                case "672":
                    Config.ReadJObject<string>(json, "command", ref cmd);
                    Config.ReadJObject<string>(json, "results[0].success", ref status);
                    Config.ReadJObject<string>(json, "requestID", ref taskId);
                    if (cmd.ToLower() == "print" && status.ToLower() == "true")
                    {
                        //YB.Log.Write("672打印完成下一个");
                        //if (taskId != "")
                        //{
                        //    AddPrintLog(printName, "文档[" + taskId + "]打印完成");
                        //}
                        goto Next;
                    }
                    break;
                case "673":
                    Config.ReadJObject<string>(json, "cmd", ref cmd);
                    Config.ReadJObject<string>(json, "status", ref status);
                    Config.ReadJObject<string>(json, "taskId", ref taskId);
                    if (cmd.ToLower() == "notifytaskresult" && status.ToLower() == "completesuccess")
                    {
                        //YB.Log.Write("673打印完成下一个");
                        //if (taskId != "")
                        //{
                        //    AddPrintLog(printName, "文档[" + taskId + "]打印完成");
                        //}
                        goto Next;
                    }
                    break;
                case "638":
                    Config.ReadJObject<string>(json, "cmd", ref cmd);
                    Config.ReadJObject<string>(json, "result", ref status);
                    Config.ReadJObject<string>(json, "traceId", ref taskId);
                    if (cmd.ToLower() == "print" && status.ToLower() == "success")
                    {
                        //YB.Log.Write("638打印完成下一个");
                        //if (taskId != "")
                        //{
                        //    AddPrintLog(printName, "文档[" + taskId + "]打印完成");
                        //}
                        goto Next;
                    }
                    break;
            }
            return "";
        Next:
            return taskId;
        }
        private static int ExtractNumber(string input)
        {
            string numberPattern = @"\d+"; // 正则表达式匹配数字
            Match match = Regex.Match(input, numberPattern);

            // 如果找到匹配的数字，则返回第一个匹配结果
            if (match.Success)
            {
                return int.Parse(match.Value);
            }

            // 如果没有找到匹配的数字，则返回默认值 0
            return 0; 
        }
        private void _init()
        {
            while (true)
            {
                try
                {
                    using (TcpClient client = new TcpClient())
                    {
                        try
                        {
                            client.ReceiveTimeout = 2000; // 设置连接超时时间为2秒
                                                          // 尝试连接到目标IP和端口
                            client.Connect(_ip, ExtractNumber(_prot));
                            if (client.Connected)
                            {
                                client.Close();
                            }
                            // 连接成功
                            if (_sendSocket == null)
                            {
                                _sendSocket = new WebSocketSharp.WebSocket("ws://" + _ip + ":" + _prot.ToString()); // 这里的URL是WebSocket服务器的地址
                                _sendSocket.OnMessage += onmessage;
                                _sendSocket.OnOpen += onopen;
                                _sendSocket.OnClose += onclose;
                                _sendSocket.Connect();
                                _inLink = false;
                                return;
                            }
                            else if (_sendSocket != null && !_sendSocket.IsAlive)
                            {
                                try
                                {
                                    _sendSocket.Connect();
                                }
                                catch (SocketException ex)
                                {
                                    //Console.WriteLine(ex.ToString());
                                }
                                catch (Exception ex)
                                {

                                }
                            }
                        }
                        catch (SocketException ex)
                        {
                            //Console.WriteLine(ex.ToString());
                        }
                        catch (Exception ex)
                        {
                            
                        }
                    }
                }
                catch (SocketException ex)
                {
                    //Console.WriteLine(ex.ToString());
                }
                catch (Exception ex)
                {
                    // 连接失败或超时

                }

                // 等待1秒后继续下一次连接测试
                System.Threading.Thread.Sleep(2000);
            }
        }
        public Image GetImage()
        {
            return _imageData;
        }
        public void Continue(string printname)
        {
            if (_printMap.ContainsKey(printname))
            {
                _printMap[printname].Continue();
            }
        }
        public void Clear(string printname)
        {
            if (_printMap.ContainsKey(printname))
            {
                _printMap[printname].Clear();
            }
        }
        public void SendMsg(string data)
        {
            //lock (_lockObject)
            //{
                if (_sendSocket != null && _sendSocket.IsAlive)
                {
                    _sendSocket.Send(data);
                    Thread.Sleep(200);//100毫秒最多发送1个指令给打印组件
                }
            //}
        }
        public void Send(string printname, string data, IWebSocketConnection socket)
        {
            if (_socket == null)
            {
                _socket = socket;
            }
            if (_printMap.ContainsKey(printname))
            {
                _printMap[printname].Send(data);
            }
            else
            {
                PrintChannel newMap = new PrintChannel(printname, data, this);
                _printMap.TryAdd(printname, newMap);
            }
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            this.BackColor = Color.Transparent;
            //绘制图标
            e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            if (_imageData != null)
            {
                if (_linkStatus)
                {
                    e.Graphics.DrawImage(_imageData, 11, 11, 48, 48);
                }
                else
                {
                    var grayImageData = ConvertToGrayscale(_imageData);
                    e.Graphics.DrawImage(grayImageData, new Rectangle(11, 11, 48, 48));
                }
            }
            //绘制标签
            if (_label != null)
            {
                using (Font font = SystemFonts.DefaultFont)
                {
                    using (SolidBrush brush = new SolidBrush(Color.Black))
                    {
                        StringFormat format = new StringFormat();
                        format.Alignment = StringAlignment.Center;
                        format.LineAlignment = StringAlignment.Center;
                        RectangleF rect = new RectangleF(2, 65, this.Width - 2, 30); // 设置文字区域，减去边界宽度
                        e.Graphics.DrawString(_label, font, brush, rect, format);
                    }
                }
            }
            //绘制状态
            var brushicon = new SolidBrush(Color.Red);
            // 设置边线颜色
            var pen = new Pen(Color.Black, 1);
            if (LinkStatus)
            {
                brushicon = new SolidBrush(Color.LightGreen);
            }
            int x = 56;  // 圆心 x 坐标
            int y = 14;  // 圆心 y 坐标
            int radius = 6;  // 圆的半径
            // 绘制填充的圆形
            e.Graphics.FillEllipse(brushicon, x - radius, y - radius, radius * 2, radius * 2);
            // 绘制边线的圆形
            e.Graphics.DrawEllipse(pen, x - radius, y - radius, radius * 2, radius * 2);
            if (_SendCount > 0)
            {
                using (Font font = SystemFonts.DefaultFont)
                {
                    using (SolidBrush brush = new SolidBrush(Color.Black))
                    {
                        StringFormat format = new StringFormat();
                        format.Alignment = StringAlignment.Center;
                        format.LineAlignment = StringAlignment.Center;
                        RectangleF rect = new RectangleF(1, 90, this.Width - 2, 20); // 设置文字区域，减去边界宽度
                        e.Graphics.DrawString("发送:" + _SendCount.ToString(), font, brush, rect, format);
                    }
                }
            }
            if (_receiveCount > 0)
            {
                using (Font font = SystemFonts.DefaultFont)
                {
                    using (SolidBrush brush = new SolidBrush(Color.Black))
                    {
                        StringFormat format = new StringFormat();
                        format.Alignment = StringAlignment.Center;
                        format.LineAlignment = StringAlignment.Center;
                        RectangleF rect = new RectangleF(1, 100, this.Width - 2, 20); // 设置文字区域，减去边界宽度
                        e.Graphics.DrawString("接收:" + _receiveCount.ToString(), font, brush, rect, format);
                    }
                }
            }
            if (mouseinplug && !_linkStatus)
            {
                //如果鼠标移入并且没有链接上，则绘制下载
                Rectangle rect = new Rectangle(15, 15, 40, 35);
                SolidBrush solidBrush = new SolidBrush(Color.FromArgb(0xff, 0xa0, 0xdf, 0xff));
                PopupWindow.DrawRoundedRectangle(g, pen, solidBrush, rect, 4);
                StringFormat format = new StringFormat();
                format.Alignment = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;
                var font = SystemFonts.DefaultFont;
                var brush = new SolidBrush(Color.Black);
                g.DrawString("下载组件", font, brush, rect, format);
            }
        }
        private static Bitmap ConvertToGrayscale(Image image)
        {
            // 创建一个新的灰度图像
            Bitmap grayscaleImage = new Bitmap(image.Width, image.Height);

            // 设置灰度图像的颜色空间
            Graphics g = Graphics.FromImage(grayscaleImage);
            ColorMatrix colorMatrix = new ColorMatrix(new float[][]
            {
            new float[] {0.299f, 0.299f, 0.299f, 0, 0},
            new float[] {0.587f, 0.587f, 0.587f, 0, 0},
            new float[] {0.114f, 0.114f, 0.114f, 0, 0},
            new float[] {0, 0, 0, 1, 0},
            new float[] {0, 0, 0, 0, 1}
            });
            ImageAttributes attributes = new ImageAttributes();
            attributes.SetColorMatrix(colorMatrix);
            g.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height),
                0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);

            return grayscaleImage;
        }
    }
}
